package cn.tedu.zx.court.adapter.impl;


import cn.tedu.zx.common.exception.ServiceException;
import cn.tedu.zx.common.restful.JsonPage;
import cn.tedu.zx.common.restful.ResponseCode;
import cn.tedu.zx.court.adapter.mapper.CategoryMapper;
import cn.tedu.zx.court.adapter.mapper.CourtMapper;
import cn.tedu.zx.court.service.CategoryService;
import cn.tedu.zx.pojo.court.dto.CategoryAddNewDto;
import cn.tedu.zx.pojo.court.dto.CategoryUpdateDto;
import cn.tedu.zx.pojo.court.entity.Category;
import cn.tedu.zx.pojo.court.entity.Court;
import cn.tedu.zx.pojo.court.vo.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Service
public class CategoryServiceImpl implements CategoryService {
    private String message = null;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private CourtMapper courtMapper;

    Category category = new Category();

//    增加类别
    @Override
    public void addNew(CategoryAddNewDto categoryAddNewDto) {
        log.debug("往分类添加文件");

        Long parentId = categoryAddNewDto.getParentId();
        if (parentId == null) {
            parentId = 0L;
        }

        //检查数据冲突情况
        checkConflict(categoryAddNewDto.getName(), parentId, 0L);

        Integer depth = 1;
        CategoryDetailsVo categoryParentVo = categoryMapper.selectDetailsById(parentId);
        if (parentId != 0) {
            if (categoryParentVo == null) {
                message = "操作失败，父级类别不存在";
                throw new ServiceException(ResponseCode.NOT_FOUND, message);
            }
            depth = categoryParentVo.getDepth() + 1;
        }
        BeanUtils.copyProperties(categoryAddNewDto, category);
        category.setDepth(depth);
        category.setIsParent(0).setParentId(parentId);
        category.setCreated(LocalDateTime.now());
        category.setUpdated(LocalDateTime.now());
        log.trace("往数据库添加子项：{}", category);
        int insert = categoryMapper.insert(category);

        //检查操作是否全部成功
        operateFailed(insert);
        log.trace("{}添加分类完成", category);

        //修改父级的IsParent
        setParent(categoryParentVo);
    }


    @Override
    public void deleteById(Long id) {
        log.debug("{}", id);
        //检查数据是否存在
        checkEmpty(id);

        CategoryDetailsVo categoryDetailsVo = selectDetailsById(id);
        Long parentId = categoryDetailsVo.getParentId();

        /*相片下是否存在关联数据*/
        QueryWrapper<Court> courtWrapper = new QueryWrapper();
        courtWrapper.eq("category_id", id);
        int countByCategoryId = courtMapper.selectCount(courtWrapper);
        if (countByCategoryId > 0) {
            message = "删除分类失败，场地下存在关联数据";
            log.warn(message);
            throw new ServiceException(ResponseCode.CONFLICT, message);
        }

        //该级别下存在子级则不允许删除
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("parent_id", id);
        Integer integer = categoryMapper.selectCount(queryWrapper);
        if (integer > 0) {
            message = "存在子级数据";
            throw new ServiceException(ResponseCode.NOT_ACCEPTABLE, message);
        }

        int delete = categoryMapper.deleteById(id);

        //检查操作是否全部成功
        operateFailed(delete);

        log.trace("{}删除成功", categoryDetailsVo);

//        处理父子级关系
        setNoParent(parentId);

    }


    @Override
    public void updateById(CategoryUpdateDto categoryUpdateDto) {
        log.debug("{}", categoryUpdateDto);

        Long id = categoryUpdateDto.getId();

        //检查数据是否存在
        checkEmpty(id);

        Long parentId = categoryUpdateDto.getParentId();
        //检查数据冲突情况
        checkConflict(categoryUpdateDto.getName(), parentId, id);

        //检查相关数据冲突情况
        //该级别下存在子级则不允许修改父级id
        CategoryDetailsVo categoryDetailsVo = categoryMapper.selectDetailsById(id);
        Long oldParentId = categoryDetailsVo.getParentId();
        if (!parentId.equals(oldParentId)) {
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("parent_id", id);
            Integer integer = categoryMapper.selectCount(queryWrapper);
            if (integer > 0) {
                message = "存在子级数据";
                throw new ServiceException(ResponseCode.NOT_ACCEPTABLE, message);
            }
        }

        BeanUtils.copyProperties(categoryUpdateDto, category);
        category.setUpdated(LocalDateTime.now());
        log.trace("往数据库修改子项：{}", category);
        int updateById = categoryMapper.updateById(category);

        //检查操作是否全部成功
        operateFailed(updateById);
        log.trace("{}修改完成", category);

//        处理原父子级关系
        setNoParent(oldParentId);

//        处理新的父子级关系
        CategoryDetailsVo newDetailsVo = categoryMapper.selectDetailsById(parentId);
        setParent(newDetailsVo);


    }

    @Override
    public CategoryDetailsVo selectDetailsById(Long id) {
        log.debug("传入的id：{}", id);
        CategoryDetailsVo categoryDetailsVO = categoryMapper.selectDetailsById(id);
        log.debug("查到的数据：{}", categoryDetailsVO);
        if (categoryDetailsVO == null) {
            message = "查询失败，根据【id=" + id + "】查询的分类详情不存在";
            log.warn(message);
            throw new ServiceException(ResponseCode.NOT_FOUND, message);
        }
        return categoryDetailsVO;
    }

    @Override
    public JsonPage<CategoryListVo> list(Integer pageNum, Integer pageSize) {
        System.out.println(pageNum);
        System.out.println(pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<CategoryListVo> list = categoryMapper.list();
        PageInfo<CategoryListVo> pageInfo = new PageInfo<>(list);
        return JsonPage.restPage(pageInfo);
    }

    @Override
    public List<TreeListVo> treeList() {
        List<CategoryListVo> list = categoryMapper.list();
        List<TreeListVo> treeList = new ArrayList<>();
        Map<Long, CategoryListVo> allMap = new LinkedHashMap();
        for (CategoryListVo item : list) {
            allMap.put(item.getId(), item);
        }

        for (Long key : allMap.keySet()) {
            CategoryListVo item = allMap.get(key);
            if (item.getParentId() == 0) {
                TreeListVo treeListVo = tranFromCategoryToTreeList(item);
                treeList.add(treeListVo);

                fillChildren(item, treeListVo, allMap);
            }
        }
        return treeList;
    }

    @Override
    public List<Long> defaultList(Long id) {
        List<CategoryDefaultVo> list = categoryMapper.selectDefault();
        List<Long> list1 = new ArrayList<>();
        Long parentId = id;
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).getId().equals(parentId)) {
                if (list.get(i).getParentId() != 0) {
                    parentId = list.get(i).getParentId();
                    list1.add(parentId);
                    i = 0;
                } else {
                    break;
                }
            }
        }
        Collections.reverse(list1);
        System.out.println(list1);
        return list1;
    }

    @Override
    public List<CategoryIdNameList> getIdAndName(Long id) {
        List<CategoryIdNameList> list = categoryMapper.getIdAndName(id);
        return list;
    }

    @Override
    public List<CategoryIdNameList> getFrontIdAndName() {
        List<CategoryIdNameList> list = categoryMapper.getFrontIdAndName();
        return list;
    }

    /**
     * 将CategoryListVo转成TreeListVo类型
     *
     * @param itemListVo
     * @return
     */
    private TreeListVo tranFromCategoryToTreeList(CategoryListVo itemListVo) {
        TreeListVo treeListVo = new TreeListVo();
        treeListVo.setValue(itemListVo.getId());
        treeListVo.setLabel(itemListVo.getName());
        return treeListVo;
    }

    /**
     * 对列表树的子级进行填充
     *
     * @param listItem
     * @param currentTreeItem
     * @param allCategoryMap
     */
    private void fillChildren(CategoryListVo listItem,
                              TreeListVo currentTreeItem,
                              Map<Long, CategoryListVo> allCategoryMap) {
        if (listItem.getIsParent() == 1) {
            currentTreeItem.setChildren(new ArrayList<>());
            Set<Long> keySet = allCategoryMap.keySet();
            for (Long key : keySet) {
                CategoryListVo mapItem = allCategoryMap.get(key);
                if (mapItem.getParentId() == listItem.getId()) {
                    TreeListVo categoryTreeSubItemVO = tranFromCategoryToTreeList(mapItem);
                    currentTreeItem.getChildren().add(categoryTreeSubItemVO);
                    if (mapItem.getIsParent() == 1) {
                        fillChildren(mapItem, categoryTreeSubItemVO, allCategoryMap);
                    }
                }
            }
        }

    }


    /**
     * 通过id检查数据是否存在
     *
     * @param id
     */
    private void checkEmpty(Long id) {
        QueryWrapper<Category> albumWrapper = new QueryWrapper();
        albumWrapper.eq("id", id);
        int countById = categoryMapper.selectCount(albumWrapper);
        if (countById == 0) {
            message = "操作失败，数据不存在";
            log.warn(message);
            throw new ServiceException(ResponseCode.NOT_FOUND, message);
        }
    }

    /**
     * 文件操作是否与预测一致
     *
     * @param operatedRows
     */
    private void operateFailed(Integer operatedRows) {
        if (operatedRows < 1) {
            String message = "服务器忙,请稍后再试";
            throw new ServiceException(ResponseCode.INTERNAL_SERVER_ERROR, message);
        }
    }


    /**
     * 通过名称字段及id检查内容是否冲突
     *
     * @param name
     * @param parentId
     * @param id
     */
    private void checkConflict(String name, Long parentId, Long id) {
        QueryWrapper<Category> categoryWrapper = new QueryWrapper();
        categoryWrapper.eq("parent_id", parentId)
                .ne("id", id)
                .eq("name", name);
        int countByName = categoryMapper.selectCount(categoryWrapper);
        log.debug("查询数据{}", countByName);
        if (countByName > 0) {
            message = "操作失败，分类名已占用";
            log.warn(message);
            throw new ServiceException(ResponseCode.CONFLICT, message);
        }
    }

    /**
     * 检查父类id设置为非父级
     * @param parentId
     */
    private void setNoParent(Long parentId){
        QueryWrapper queryWrapper1 = new QueryWrapper();
        queryWrapper1.eq("parent_id", parentId);
        Integer rows = categoryMapper.selectCount(queryWrapper1);
        log.trace("查询父级完成:{}", rows);
        if (rows == 0 && parentId != 0) {
            Category category1 = new Category();
            category1.setId(parentId);
            category1.setIsParent(0);
            category1.setUpdated(LocalDateTime.now());
            int update = categoryMapper.updateById(category1);
            operateFailed(update);
            log.trace("{}修改完成", category1);
        }
    }

    /**
     *检查父类情况设置为父级
     * @param categoryDetailsVo
     */
    private void setParent(CategoryDetailsVo categoryDetailsVo){
        if (categoryDetailsVo != null) {
            Integer isParent = categoryDetailsVo.getIsParent();
            if (isParent == 0) {
                Category category1 = new Category();
                category1.setId(categoryDetailsVo.getId());
                category1.setIsParent(1);
                category1.setUpdated(LocalDateTime.now());
                int update = categoryMapper.updateById(category1);
                operateFailed(update);
                log.trace("{}修改父级完成", category1);
            }
        }
    }

}
